package com.xiashitech.agent.service;

import java.net.JarURLConnection;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 一个简单的服务注册器
 * @author zhaoyk
 * @param <I> 服务接口类型
 */
@SuppressWarnings("unchecked")
public class ServiceRegister<I> {

    private Class<I> serviceInterface;

    private Map<String, I> serviceMap;

    public ServiceRegister(Class<I> serviceInterface) {
        this(serviceInterface, null);
    }

    public ServiceRegister(Class<I> serviceInterface, String scanPackage) {
        this.serviceInterface = serviceInterface;
        this.serviceMap = new HashMap<>();

        if(scanPackage != null && scanPackage.length() > 0)
            scan(scanPackage);
    }

    public <T extends I> T regService(T serviceObj, String name) {
        serviceMap.put(name, serviceObj);
        return serviceObj;
    }

    public <T extends I> T regService(T serviceObj) {
        return regService(serviceObj, serviceObj.getClass().getSimpleName());
    }

    public <T extends I> T regService(Class<T> implClass, String name) {
        try {
            return regService(implClass.newInstance(), name);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public <T extends I> T regService(Class<? extends T> serviceImpl) {
        return regService(serviceImpl, serviceImpl.getSimpleName());
    }

    public <T extends I> T getService(String name) {
        return (T)serviceMap.get(name);
    }

    public <T extends I> T getService(Class<T> implClass) {
        for (I value : serviceMap.values()) {
            if(value.getClass() == implClass)
                return (T)value;
        }
        return null;
    }

    public Collection<I> getServices() {
        return serviceMap.values();
    }

    public boolean hasService() {
        return !serviceMap.isEmpty();
    }

    public void scan(String scanPackage) {
        try {
            Enumeration<URL> urls = ClassLoader.getSystemClassLoader().getResources(scanPackage.replace('.', '/'));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("jar")) { //agent.jar
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        JarFile jarFile = jarURLConnection.getJarFile();
                        Enumeration<JarEntry> jarEntries = jarFile.entries();
                        String packagePre = scanPackage + ".";
                        while (jarEntries.hasMoreElements()) {
                            JarEntry jarEntry = jarEntries.nextElement();
                            String jarEntryName = jarEntry.getName();
                            if (jarEntryName.endsWith(".class")) {
                                String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                if (className.startsWith(packagePre)) {
                                    try {
                                        Class<?> cls = serviceInterface.getClassLoader().loadClass(className);
                                        if(serviceInterface.isAssignableFrom(cls) && cls != serviceInterface)
                                            regService((Class<? extends I>) cls);
                                    } catch (Throwable t) {

                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {

        }
    }

}
